package org.penguin.boot.security.initial;

import lombok.extern.slf4j.Slf4j;
import org.penguin.boot.security.dao.PrivilegeRepository;
import org.penguin.boot.security.dao.RoleRepository;
import org.penguin.boot.security.entity.Privilege;
import org.penguin.boot.security.entity.Role;
import org.penguin.boot.security.entity.User;
import org.penguin.boot.security.service.UserService;
import org.penguin.boot.security.util.SaltUtil;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextRefreshedEvent;
import org.springframework.stereotype.Component;

import javax.transaction.Transactional;
import java.util.*;

@Slf4j
@Component
public class InitialEnvironment implements ApplicationListener<ContextRefreshedEvent> {
    /**
     * 需要初始化数据时，使用
     */
    boolean alreadySetup = false;

    private final UserService userService;

    private final RoleRepository roleRepository;

    private final PrivilegeRepository privilegeRepository;

    public InitialEnvironment(UserService userService, RoleRepository roleRepository, PrivilegeRepository privilegeRepository) {
        this.userService = userService;
        this.roleRepository = roleRepository;
        this.privilegeRepository = privilegeRepository;
    }

    @Override
    @Transactional
    public void onApplicationEvent(ContextRefreshedEvent event) {
        log.info("应用启动后或上下文环境变化时，会执行！");
        if (alreadySetup)
            return;
        Privilege readPrivilege = createPrivilegeIfNotFound("READ_USER_PRIVILEGE");
        Privilege writePrivilege = createPrivilegeIfNotFound("WRITE_USER_PRIVILEGE");

        List<Privilege> adminPrivileges = Arrays.asList(readPrivilege, writePrivilege);
        createRoleIfNotFound("ROLE_ADMIN", adminPrivileges);
        createRoleIfNotFound("ROLE_USER", Collections.singletonList(readPrivilege));

        Optional<Role> adminRole = roleRepository.findByName("ROLE_ADMIN");
        if (adminRole.isPresent()) {
            User admin = new User();
            admin.setFullName("系统管理员");
            admin.setNickName("大魔王竹轻风");
            admin.setSalt(SaltUtil.generateSalt());
            admin.setPassword("12xy34ZV");
            admin.setEmail("admin@penguin.org");
            admin.setRoles(Collections.singletonList(adminRole.get()));
            admin.setEnabled(true);
            userService.createUser(admin);
        }

        Optional<Role> userRole = roleRepository.findByName("ROLE_USER");
        if (userRole.isPresent()) {
            User user = new User();
            user.setFullName("员工甲");
            user.setNickName("Java工程师");
            user.setSalt(SaltUtil.generateSalt());
            user.setPassword("12xy34ZV");
            user.setEmail("userA@penguin.org");
            user.setRoles(Collections.singletonList(userRole.get()));
            user.setEnabled(true);
            userService.createUser(user);
        }
        alreadySetup = true;
    }

    @Transactional
    public Privilege createPrivilegeIfNotFound(String name) {
        Privilege privilege = privilegeRepository.findByName(name);
        if (privilege == null) {
            privilege = new Privilege(name);
            privilegeRepository.save(privilege);
        }
        return privilege;
    }

    @Transactional
    public Role createRoleIfNotFound(String name, Collection<Privilege> privileges) {
        Optional<Role> optionalRole = roleRepository.findByName(name);
        Role role;
        if (optionalRole.isPresent()) {
            role = optionalRole.get();
        } else {
            role = new Role(name);
            role.setPrivileges(privileges);
            roleRepository.save(role);
        }
        return role;
    }
}
